/**
 * Copyright 2010 Victor Egea Hernando
 *
 * RockScript is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, version 3 of the License.
 * 
 * RockScript is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with RockScript.  If not, see <http://www.gnu.org/licenses/>.
 */
#ifndef METHOD_H_
#define METHOD_H_

#include "../types.h"

#include "vmtypes.h"
#include "opcodes.h"
#include "instruction.h"
#include "picojit/pjit_block.h"

namespace paper{

class vmachine;
class vm_class;
class method;

enum{
	FLG_MTHD_DEFINED = 1, FLG_MTHD_STATIC = 2, FLG_MTHD_CPP = 4
};

// cpp method pointer 
typedef corelib::int32 (* cpp_method) ( vmachine &, method &, corelib::uint32 pc );

class PAPER_API method{

public:
	// CONSTRUCTIRS AND DESTRUCTOR
    method( const corelib::ustring &name, vm_class *pclass, corelib::uint32 midx,
	const corelib::ustring &meta = "", corelib::uint32 nargs = 0 );
	virtual ~method();

public:
	// COMPILER NTERFACE
	bool add_inst_a( corelib::uint8 op, corelib::uint8 a, corelib::uint8 b, corelib::uint8 c );
	bool add_inst_b( corelib::uint8 op, corelib::uint8 a, corelib::int16 z );
	bool set_stack_frame_size( corelib::uint32 nlvars, corelib::uint32 neregs );
	corelib::uint32 add_constant( const __register &reg );
	void set_flags( corelib::uint32 flags );
	void set_cpp_handler( cpp_method ptr );

public:
	// GETTERS
	const corelib::ustring &name( void ) const{ return _name; }
	const corelib::ustring &meta_name( void ) const{ return _meta_name; }
	corelib::uint32 flags( void ) const{ return _flags; }
	corelib::uint32 nargs( void ) const { return _nargs; }
	corelib::uint32 idx( void ) const { return _idx; }
	vm_class *pclass( void ) const { return _pclass; }
	pjit::pjit_block &block( void ){ return _block; }

protected:
	// MAIN STRUCTURES
	std::vector<__register> _constant;
	std::vector<instruction> _opcode;
	pjit::pjit_block _block;

	// OTHER PROPERTIES
	corelib::uint32 _sfstack, _flags;
	corelib::ustring _name, _meta_name;
	corelib::uint32 _idx, _nargs;
	corelib::real32 _cycles;
	vm_class *_pclass;
	cpp_method _mptr;

protected:
	// friends
	friend class paper2lir;
	friend class vmachine;
	friend class vm_class;
	friend class routine;

};

}; // namespace paper

// prints the method
PAPER_API std::ostream &operator << ( std::ostream &os, const paper::method &method );

#endif // METHOD_H_
